
//For dataPlot legends
MyLocation loLegend;


//For radius legends
//Radius: show earthquakes inside certain area with current radius
MyLocation loRadius;


class MagnitudeLegend
{
  private String [] strLegend;
  private String [] strLegendDes;
  private int numOfLegend ;
  private color [] colorPoints; 
  private color [] blindColorPoints;
  private float [] gradeValue;

  public  float x1;
  public   float y1;
  public   float w;
  public   float h;
  private PImage handle;
  private float [] handlePos ;
  private float topSpace; //The space between y1 and legend top
  private int top;
  private int bottom;
  private float handleLeft;
  private float handleRight;
  private float handleTop;
  private float handleBottom;
  private int dragMode ;
  private int handleHeight;
  private int handleWidth;
  float handleY;
  private boolean isBlind;

  MagnitudeLegend( float x, float y, float wei, float hei, boolean blind)
  {

    x1= x;
    y1 = y;
    w = wei;
    h = hei;
    numOfLegend =8;
    handle = loadImage("magnitudeSliderHandle.png");
    handlePos = new float [numOfLegend+1];
    loLegend = new MyLocation(x1,y1,w,h );
    top = 0 ;
    bottom = 8;
    dragMode = 0 ;
    setupColors();
    setupLegend();
    isBlind = blind;
  }

  private void setupColors()
  {
    //Richter Scale
    colorPoints = new color[8];
       colorPoints[0] = color(#009999);  //Magnitude<2.2
    colorPoints[1] = color(#00C90D);  //Magnitude 2.2-3.5
    colorPoints[2] = color(#F7FE00);  //Magnitude 3.5-4.0
    colorPoints[3] = color(#FFDB00);  //Magnitude 4.0-5.0
    colorPoints[4] = color(#FFC200);  //Magnitude 5.0-6.0
    colorPoints[5] = color(#FFA700);  //Magnitude 6.0-7.0
    colorPoints[6] = color(#FF7400);  //Magnitude 7.0-8.0
    colorPoints[7] = color(#FF4100);  //Magnitude>8.0
    
    blindColorPoints =  new color[8];
    blindColorPoints[0] = color(#ffffcc);  //Magnitude<2.2
    blindColorPoints[1] = color(#ffeda0);  //Magnitude 2.2-3.5
    blindColorPoints[2] = color(#fed976);  //Magnitude 3.5-4.0
    blindColorPoints[3] = color(#feb24c);  //Magnitude 4.0-5.0
    blindColorPoints[4] = color(#fd8d3c);  //Magnitude 5.0-6.0
    blindColorPoints[5] = color(#fc4e2a);  //Magnitude 6.0-7.0
    blindColorPoints[6] = color(#e31a1c);  //Magnitude 7.0-8.0
    blindColorPoints[7] = color(#bd0026);  //Magnitude>8.0
  }
  
  public void changeColorMode()
  {
    isBlind = !isBlind;
  }

  int getColorIndex( float m)
  {
    int index = -1 ;
    for( int i = 0 ; i< numOfLegend;i++)
    {
      if( i ==0)
      {
        if( m<= gradeValue[i] && m>0 )
          index = i;
      }
      else
      {
        if( m<= gradeValue[i] && m>gradeValue[i-1])
          index = i;
      }
    }
    if( index!=-1)
      return index;
    else
    {
      println("Out of color boundary!!!");
      return -1;
    }
  }
  color getColor( int index)
  {
    if( !isBlind) 
    return colorPoints[index];
    else
    return blindColorPoints[index];
  }

  private void setupLegend()
  {
    gradeValue = new float [numOfLegend ];
    gradeValue[0] = 2.2;
    gradeValue[1] = 3.5;
    gradeValue[2] = 4.0;
    gradeValue[3] = 5.0;
    gradeValue[4] = 6.0;
    gradeValue[5] = 7.0;
    gradeValue[6] = 8.0;
    gradeValue[7] = 9.9;

    strLegend = new String [numOfLegend];
    strLegend[0] = "Below 2.2";
    strLegend[1] = "2.2 - 3.5";
    strLegend[2] = "3.5 - 4.0";
    strLegend[3] = "4.0 - 5.0";
    strLegend[4] = "5.0 - 6.0";
    strLegend[5] = "6.0 - 7.0";
    strLegend[6] = "7.0 - 8.0";
    strLegend[7] = "8.0 and up";
    
    strLegendDes = new String [numOfLegend];
    strLegendDes[0] = "Microquake";
    strLegendDes[1] = "Most people aware that an earthquake has occurrede";
    strLegendDes[2] = "Slight damage";
    strLegendDes[3] = "Moderate damage";
    strLegendDes[4] = "Considerable damage";
    strLegendDes[5] = "Severe damage";
    strLegendDes[6] = "Major earthquake, capable of widespread heavy damage";
    strLegendDes[7] = "Great earthquake, capable of total damage/loss";
  }

  public void render()
  {
    try {
      float leftSpace = 20;
      float leading =25;
      //fill(196,189,182);
      fill(190,209,216);
      rect(loLegend.x1,loLegend.y1,loLegend.getWidth(),loLegend.getHeight() );
      fill(0,0,0);
      textSize(12);
      textAlign(CENTER);
      text("MAGNITUDES\n(Richter Scale)", loLegend.x1+leftSpace, loLegend.y1+leftSpace-5, loLegend.getWidth()-2*leftSpace, 40);
      textAlign(LEFT,CENTER);
      float height = 180;
      float width = 15;
      float scale = height / 9.9;
      float left = x1 +leftSpace +15;
      float tempHeight = 0 ;
      float textHeight = 0 ;
      topSpace = loLegend.y1+leftSpace+40;

      handlePos[0] =0;

      for( int i = 0 ;i< numOfLegend ;i++)
      {  

        //ellipse(loLegend.x1+leftSpace+15, loLegend.y1+leftSpace+40+i*leading + 7, 7+2*(i+1), 7+2*(i+1)  );
        //Change the magnitude legend to slider    
        if( !isBlind)
          fill(colorPoints[i]);   
          else
          fill(blindColorPoints[i]);
        if( i == 0) //0-2.2
        {
          rect( left, topSpace +tempHeight,width, (gradeValue[i] -0)*scale  );

          tempHeight += (gradeValue[i] -0)*scale;
          handlePos[i+1] = tempHeight;
          textHeight = (gradeValue[i] -0)*scale;
        }
        else
        {
          rect( left, topSpace+tempHeight,width, (gradeValue[i] -gradeValue[i-1])*scale  );
          tempHeight += (gradeValue[i] -gradeValue[i-1])*scale;
          handlePos[i+1] = tempHeight;
          textHeight =(gradeValue[i] -gradeValue[i-1])*scale ;
        }
        fill(0,0,0);
        //println ( "handlePos["+(i+1)+"] is" +handlePos[i+1]);
        if( textHeight<10)
          textHeight = 15;
        textSize(12);
        textAlign(LEFT,CENTER);
        text(strLegend[i],loLegend.x1+leftSpace+40, topSpace +tempHeight-textHeight, loLegend.getWidth()-2*leftSpace, textHeight);
        if(mouseX>=loLegend.x1+leftSpace+40&& mouseX< loLegend.x1+leftSpace+40+loLegend.getWidth()-2*leftSpace && mouseY>=topSpace +tempHeight-textHeight && mouseY<topSpace +tempHeight-textHeight+textHeight)
             drawLegendDes(mouseX,mouseY,i); 
      }
      handleWidth = int(width);
      handleHeight = int(width);
      handleY=loLegend.y1+leftSpace+40;
      handleTop = loLegend.y1+leftSpace+40 + handlePos[top];
      handleBottom = loLegend.y1+leftSpace+40+handlePos[bottom];
      drawHandle(left+width/2,handleTop,handleWidth,handleHeight);
      drawHandle(left+width/2,handleBottom,handleWidth,handleHeight); 
      handleLeft = left;
      handleRight =left+width;
    }
    catch(NullPointerException npe) {
      println(" NP Exception, Check your code " + npe );
    }
  }

  private void drawHandle(float x,float y,float wid,float hei)
  {
    image(handle, x-wid/2-2,y-hei/2, 3*wid/2+2,hei);
  }

  public boolean mouseMoved() {
    if( mouseX>= handleLeft && mouseX<= handleRight && mouseY>= handleTop-handleHeight/2  &&mouseY<= handleTop+handleHeight/2 ) {
      cursor(HAND);
      //drawHandleHelp(mouseX,mouseY);
      return true;
    }
    else if( mouseX>= handleLeft && mouseX<= handleRight && mouseY>= handleBottom-handleHeight/2  &&mouseY<= handleBottom+handleHeight/2 ) {
      cursor(HAND);
      return true;
    }
    else {
      //cursor(CROSS);
      return false;
    }
  }

  public float getTopMagnitude()
  {
    if( top ==0)
      return 0.0;
    else
      return gradeValue[top-1];
  }
  public float getBottomMagnitude()
  {
    if( bottom ==0)
      return 0.0;
    else
      return gradeValue[bottom-1];
  }

  void drawHandleHelp ( float x, float y)
  {
    float width= 150;
    float height = 40;
    stroke(178,183,187);
    strokeWeight(1);
    fill(255,255,253);
    rect(x-width/2,y-height-5,width,height);
    fill(0);
    textSize(10);
    textAlign(CENTER,TOP);
    text("Click and drag the sliders to filter earthquake by magnitude",x-width/2,y-height,width,height);
  }
  
  void drawLegendDes ( float x, float y, int i )
  {
    float width= 150;
    float height = 40;
    stroke(178,183,187);
    strokeWeight(1);
    fill(255,255,253);
    rect(x-width/2,y-height-5,width,height);
    fill(0);
    textSize(10);
    textAlign(CENTER,CENTER);
    text(strLegendDes[i],x-width/2,y-height-5,width,height);
  }

  public void mousePressed()
  {
    //Judge if top selector
    if(mouseX>= handleLeft && mouseX<= handleRight && mouseY>= handleTop-handleHeight/2  &&mouseY<= handleTop+handleHeight/2)
    {
      dragMode = 1;
      //println("Dragmode 1");
      return;
    }
    //Judge if bottom selector
    else if(mouseX>= handleLeft && mouseX<= handleRight && mouseY>= handleBottom-handleHeight/2  &&mouseY<= handleBottom+handleHeight/2 )
    {
      dragMode = 2;
      //println("Dragmode 2");
      return;
    }
  }

  public boolean mouseDragged()
  {
    //float ix = (handleBottom-handleTop)/9;
    if(dragMode != 0)
    {
      int curPos = -10;
      int dst = 1000;
      //float curY = handleTop;
      for(int i = 0; i <= numOfLegend; i++)
      {
        int cd = int(abs(mouseY - (handleY+handlePos[i])));
        if(cd<dst)
        {
          curPos = i;
          dst = cd;
        }
      }
      if(dragMode == 1)
      {
        top = curPos;
        //if(top< 0 )
        //top= 0;
        if(top >= bottom) 
          top = bottom-1;
        //println("dst is "+dst+", curTime is "+curTime+",timeBegin is"+timeBegin);
      }
      else if(dragMode == 2)
      {
        //dayLength = curDay - dayStart + 1;
        bottom = curPos;
        if(bottom <= top) 
          bottom = top+1;
        //println("dst is "+dst+", curTime is "+curTime+",timeEnd is"+timeEnd);
      }
      return true;
    }
    return false;
  }

  void mouseReleased()
  {
    dragMode = 0;
  }
}

class RadiusLegend
{
private int numOfRadius = 5;
private float []radius;
private String []radiusDes;
private color [] colorRadius; 
private float incre;
private int highlight;
private int selected;
RadiusLegend()
{
  setupRadiusLegend();
}

  public void setupRadiusLegend()
  {
    loRadius = new MyLocation(loMap.x1,loMap.y1-50,500,30);
    radius = new float [numOfRadius];
    radiusDes = new String [numOfRadius];
    radius[0] = 50;
    radius[1] = 100;
    radius[2] = 150;
    radius[3] = 200;
    radius[4] = 250;
    //radius[5] = 25;
    //radius[6] = 30;
    // radius[7] = 40;
    //radius[8] = 50;
    //radius[9] = 100;
    for ( int i =0;i<numOfRadius;i++)
    {
      radiusDes[i] = "<"+ Float.toString(radius[i])+"KM";
    }

    colorRadius = new color[8];
    colorRadius[0] = color(#37DA7E);  //Radius<50
    colorRadius[1] = color(#33CEC3);  //Radius<50
    colorRadius[2] = color(#3E94D1);  //Radius<100
    colorRadius[3] = color(#1B1BB3);  //Radius<150
    colorRadius[4] = color(#4F10AD);  //Radius<250
    selected = -1;
  }
  
  public void render( int highLight, int clicked)
  {
    incre = loRadius.getWidth()/numOfRadius;

    for(int i = -1 ;i<numOfRadius;i++)
    {
      if( i ==-1)
      {
        fill(255,255,255);
        textAlign(LEFT,TOP);
        textSize(16);
        text("Radius",loRadius.x1, loRadius.y1 - loRadius.getHeight(),incre,loRadius.getHeight());
        float lat = curCenterLat;
        float lon = curCenterLon;
        DecimalFormat format = new DecimalFormat("0.0");
        String latString =format.format(  abs( lat)  ) ;
        String lonString =format.format( abs (lon) );
        if( lat>0)
          latString +=" N"; 
        else 
         latString += " S";
        if( lon>0)
          lonString +=" E";
         else
           lonString +=" W";
        String centerText = "Center("+latString+", "+lonString+")";
        
        textSize(14);
        float len = textWidth(centerText);
        text(centerText,loRadius.x1+ incre*numOfRadius-len, loRadius.y1 - loRadius.getHeight(),len,loRadius.getHeight());
        continue;
      }
      if( i==clicked) //mouse clicked
      {
        stroke(179,226,227);
        strokeWeight(2);      
        fill(255);
        rect(loRadius.x1+incre*i, loRadius.y1,incre,loRadius.getHeight());
        fill(colorRadius[i],80);
        rect(loRadius.x1+incre*i, loRadius.y1,incre,loRadius.getHeight());
        fill(255,255,255);
        textSize(14);
        textAlign(CENTER);
        text(radiusDes[i],loRadius.x1+incre*i, loRadius.y1+loRadius.getHeight()/4,incre,loRadius.getHeight());
        selected = clicked;
        
      }      
      else if( i==highLight) //mouse over
      {
        //println("Hightlight "+ highLight);
        stroke(255,255,255);
        strokeWeight(2);
        fill(255);
        rect(loRadius.x1+incre*i, loRadius.y1,incre,loRadius.getHeight());
        fill(colorRadius[i],80);
        rect(loRadius.x1+incre*i, loRadius.y1,incre,loRadius.getHeight());
        fill(255,255,255);
        textSize(14);
        textAlign(CENTER);
        text(radiusDes[i],loRadius.x1+incre*i, loRadius.y1+loRadius.getHeight()/4,incre,loRadius.getHeight());
      }
      else //nothing happens
      {
      stroke(255,255,255);
      strokeWeight(2);
      fill(colorRadius[i]);
      rect(loRadius.x1+incre*i, loRadius.y1,incre,loRadius.getHeight());
      fill(255,255,255);
      textSize(14);
      textAlign(CENTER);
      text(radiusDes[i],loRadius.x1+incre*i, loRadius.y1+loRadius.getHeight()/4,incre,loRadius.getHeight());
      }
      
    }
  }
  public float getRadius( int index)
  {
    return radius[index];
  }
  
  public Location [] km2Location( Location center,float km)
  {
    float latDif,lonDif=0;
    Location location [] = new Location [2];
    location[0] = new Location(0,0);
    location[1] = new Location(0,0);
    lonDif = km/111;
    latDif = km/(111*cos(center.lat*(TWO_PI/360)) );
    //topleft
    location[0].lon = center.lon - lonDif; //west is smaller
    location[0].lat = center.lat + latDif; //north is bigger
    //bottomright
    location[1].lon = center.lon + lonDif;
    location[1].lat = center.lat - lonDif;   
    
    return location;
  }
  public int mouseMoved()
 {  
    for(int i = 0 ;i<numOfRadius;i++)
    {
      if( mouseX>=loRadius.x1+incre*i && mouseX< loRadius.x1+incre*(i+1) && mouseY>= loRadius.y1&& mouseY < loRadius.y1+loRadius.getHeight() )
      {//should be highlight
            cursor(HAND);
            return i;
      }      
    }
    return -1;
 } 
 public int mouseClicked()
 {
   println("selected is "+ selected);
    for(int i = 0 ;i<numOfRadius;i++)
    {
      if( mouseX>=loRadius.x1+incre*i && mouseX< loRadius.x1+incre*(i+1) && mouseY>= loRadius.y1&& mouseY < loRadius.y1+loRadius.getHeight() )
      {//should be highlight
          if( i == selected)
          {
            if( popupRunning)
            mode = 1;
            else
            mode = 0 ;
            isFirstViewOfMode2 =true;
            selected =-1;
            return -1;
          }
          else
          {
              mode = 2;
              isFirstViewOfMode2 =true;
              selected =i;
              return i;
          }
      }      
    }
    return selected;
 }
}

